export declare type Chunk = {
  <T>(array: T[]): T[][]
  <T>(array: T[], size: number): T[][]
}

// 数组分割
export const chunk: Chunk = <T>(array: T[], size?: number) => {
  if (!size) return [array]

  const list: T[][] = []

  const len = array.length

  let i = 0

  while (i < len) {
    list.push(array.slice(i, i + size))

    i += size
  }

  return list
}

// 数组分割,接收一个数组和一个迭代函数，返回需要进入分组的索引
export const chunkBy = <T>(list: T[], iteratee: (previousValue: T[][], currentValue: T, currentIndex: number, array: T[]) => number) => {
  return list.reduce((previousValue: T[][], currentValue, currentIndex, array) => {
    const index = iteratee(previousValue, currentValue, currentIndex, array)

    index === -1 ? previousValue.push([currentValue]) : previousValue[index].push(currentValue)

    return previousValue
  }, [])
}

// 交集
export const intersection = <T>(...arrays: T[][]): T[] => {
  if (!arrays.length) return []

  const [first, ...rest] = arrays

  if (!rest || !rest.length) return first

  const [second, ...third] = rest

  const result = first.filter(item => second.includes(item))

  if (!result.length) return []

  return intersection(result, ...third)
}

// 交集
export const intersectionBy = <T, U extends (a: T, b: T[]) => boolean>(...arrays: [T[], ...T[][], U]): T[] => {
  if (!arrays.length) return []

  const [first, ...rest] = arrays

  if (typeof first === 'function' || !first.length) return []

  if (!rest || !rest.length) return first

  const iteratee = rest.pop() as U

  if (!rest.length) return first

  const [second, ...third] = rest as T[][]

  const result = first.filter(item => {
    return iteratee(item, second)
  })

  if (!result.length) return []

  return intersectionBy(result, ...third, iteratee)
}

// 并集
export const union = <T>(...arrays: T[][]): T[] => {
  if (!arrays.length) return []

  const [first, ...rest] = arrays

  if (!rest || !rest.length) return first

  return first.filter(item => {
    return intersection(...rest).includes(item)
  })
}